<?php
/**
 * 支付宝
 * */

namespace App\Lib;

use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Config;
use App\Http\Model\SystemConfig;

class Alipay
{
    //支付宝支付配置
    protected $alipayConfig = [];
    //支付宝使用配置
    protected $alipayConfigStr = 'pay_ali_app';

    public function __construct()
    {
    }

    //TODO :支付宝支付
    //设置
    public function _getOptions()
    {
        $options = new Config();
        $options->protocol = 'https';
        $options->gatewayHost = 'openapi.alipay.com';
        $options->signType = 'RSA2';
        $config = new SystemConfig();
        $config = $config->getAlipayCertPath();
//        write_log('alipay', var_export($config, true), []);
//        $options->appId = $this->alipayConfig['app_id'];
        $options->appId = explode(',',$config)[0];
        $path = explode(',', $config)[1];
        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        $options->merchantPrivateKey = file_get_contents("/data/hypd-api/cert/alipay_new/$path/key.txt");
//        $options->merchantPrivateKey = $this->alipayConfig['private_key'];
        // $options->alipayPublicKey = $this->alipayConfig['ali_public_key'];
        //支付宝公钥证书文件路径
//        $options->alipayCertPath = $this->alipayConfig['alipayCertPath'];
        $options->alipayCertPath = "/data/hypd-api/cert/alipay_new/$path/alipayCertPublicKey_RSA2.crt";
        //支付宝根证书文件路径
//        $options->alipayRootCertPath = $this->alipayConfig['alipayRootCertPath'];
        $options->alipayRootCertPath =  "/data/hypd-api/cert/alipay_new/$path/alipayRootCert.crt";
        //应用公钥证书文件路径
//        $options->merchantCertPath = $this->alipayConfig['merchantCertPath'];
        $options->merchantCertPath = "/data/hypd-api/cert/alipay_new/$path/appCertPublicKey.crt";
        //可设置异步通知接收服务地址（可选）
        //如果需要使用文件上传接口，请不要设置该参数
//        $options->notifyUrl = $this->alipayConfig['notify_url'];
        $options->notifyUrl =  env('APP_URL').'/finance/pay/alipay_notify';

        return $options;
    }

    /**
     * 设置支付配置
     */
    public function setAlipayConfig($type, $is_draw=0)
    {
        $payConfig = config('pay');
        $this->alipayConfig = [];
        if(isset($payConfig[$type])) {
            $this->alipayConfig = $payConfig[$type];
            return true;
        }
        return false;
    }

    /**
     * 统一收单交易创建接口
     */
    public function payment($subject, $outTradeNo, $totalAmount)
    {
        $orderStr = '';

        $bizParams = array(
            "subject" => $subject,
            "out_trade_no" => $outTradeNo,
            "total_amount" => $totalAmount
        );
        $textParams = array();
//        write_log("111pay", "alipay2222", $bizParams);
        try {
            Factory::setOptions($this->_getOptions());
            $result = Factory::util()->generic()->sdkExecute("alipay.trade.app.pay", $textParams, $bizParams);
            write_log("alipay", "payment result", $result);
            if(isset($result->body) && strpos($result->body, 'alipay_sdk=alipay-easysdk-php') > 0) {
                if(isset($result->body) && strpos($result->body, 'app_id='.$this->alipayConfig['app_id']) > 0) {
                    $orderStr = $result->body;
                }
            }
        } catch (\Exception $e) {
            write_log('error_alipay', 'payment', ['bizParams'=>$bizParams, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
        }

        return $orderStr;
    }

    /**
     * 统一收单交易创建接口H5
     */
    public function paymentH5($subject, $outTradeNo, $totalAmount)
    {
        $orderStr = '';

        $bizParams = array(
            "subject" => $subject,
            "out_trade_no" => $outTradeNo,
            "total_amount" => $totalAmount,
            "quit_url" => $this->alipayConfig['return_url'],
            "return_url" => $this->alipayConfig['return_url']
        );

        try {
            Factory::setOptions($this->_getOptions());

            $result = Factory::payment()->Wap()->Pay($subject, $outTradeNo, $totalAmount, $this->alipayConfig['return_url'], $this->alipayConfig['return_url']);
            if(isset($result->body) && strpos($result->body, 'alipay-easysdk-php') > 0) {
//                if(isset($result->body) && strpos($result->body, "name='app_id' value='".$this->alipayConfig['app_id']) > 0) {
                if(isset($result->body) && strpos($result->body, "name='app_id' value='".'2021004156624058') > 0) {
                    $orderStr = $result->body;
                }
            }
        } catch (\Exception $e) {
            write_log('error_alipay', 'payment', ['bizParams'=>$bizParams, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
        }

        return $orderStr;
    }

    /**
     * 统一收单交易创建接口wap
     */
    public function paymentWap($subject, $outTradeNo, $totalAmount)
    {
        $orderStr = '';
        $bizParams = array(
            "subject" => $subject,
            "out_trade_no" => $outTradeNo,
            "total_amount" => $totalAmount,
            "product_code" => 'QUICK_WAP_WAY',
            "seller_id" => '2021004156624058',
            "quit_url" => $this->alipayConfig['quit_url'],
            "return_url" => $this->alipayConfig['return_url']
        );

        try {
            Factory::setOptions($this->_getOptions());
            $result = Factory::payment()->Wap()->Pay($subject, $outTradeNo, $totalAmount, $this->alipayConfig['quit_url'], $this->alipayConfig['return_url']);
            if(isset($result->body) && strpos($result->body, 'alipay-easysdk-php') > 0) {
                if(isset($result->body) && strpos($result->body, "name='app_id' value='".$this->alipayConfig['app_id']) > 0) {
                    $orderStr = $result->body;
                }
            }
        } catch (\Exception $e) {
            write_log('error_alipay', 'payment_wap', ['bizParams'=>$bizParams, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
        }

        return $orderStr;
    }

    /**
     * 支付类异步通知验签
     */
    public function verifyNotify($parameters)
    {
        $res = null;

        try {
            Factory::setOptions($this->_getOptions());
            $check = Factory::payment()->common()->verifyNotify($parameters);
            if($check == true) {
                if($parameters['trade_status'] == 'TRADE_SUCCESS') {
                    $res = [];
                    $res['trade_status'] = 'TRADE_SUCCESS';
                    $res['out_trade_no'] = $parameters['out_trade_no'];
                    $res['trade_no'] = $parameters['trade_no'];
                }
            }

        } catch (\Exception $e) {
            write_log('error_alipay', 'verifyNotify', ['parameters'=>$parameters, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
        }

        return $res;
    }

    /**
     * 支付宝资金账户资产查询
     */
    public function accountQuery()
    {
        $availableAmount = 0;//账户可用余额，单位元，精确到小数点后两位。

        $bizParams = array(
            "alipay_user_id" => $this->alipayConfig['alipay_user_id'],
            "account_type" => 'ACCTRANS_ACCOUNT',
        );
        $textParams = array();

        try {
            $this->setAlipayConfig($this->alipayConfigStr);

            Factory::setOptions($this->_getOptions());
            $result = Factory::util()->generic()->execute("alipay.fund.account.query", $textParams, $bizParams);
            if(isset($result->httpBody) && !empty($result->httpBody)) {
                $result = json_decode($result->httpBody, true);
                if(isset($result['alipay_fund_account_query_response']['code'])) {
                    if($result['alipay_fund_account_query_response']['code'] == 10000) {
                        $availableAmount = $result['alipay_fund_account_query_response']['available_amount']*100;
                    }
                }
            }
        } catch (\Exception $e) {
            write_log('error_alipay', 'fundAccountQuery', ['bizParams'=>$bizParams, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
        }

        return $availableAmount;
    }

    /**
     * 支付宝单笔转账
     */
    public function transUniTransfer($outBizNo, $transAmount, $identity, $name)
    {
        $result = [
            'code' => 99,
            'msg' => '失败',
            'data' => [],
        ];
        do {
            $bizParams = array(
                //商家侧唯一订单号，由商家自定义。对于不同转账请求，商家需保证该订单号在自身系统唯一。
                "out_biz_no" => $outBizNo,
                //订单总金额，单位为元，不支持千位分隔符，精确到小数点后两位，取值范围[0.1,100000000]。
                "trans_amount" => $transAmount,
                "biz_scene" => 'DIRECT_TRANSFER',
                "product_code" => 'TRANS_ACCOUNT_NO_PWD',
                //转账业务的标题，用于在支付宝用户的账单里显示。
                "order_title" => '金币提现',
                //收款方信息
                "payee_info" => [
                    //参与方的标识 ID。支付宝登录号
                    "identity" => $identity,
                    //参与方的标识类型:支付宝登录号
                    "identity_type" => 'ALIPAY_LOGON_ID',
                    //参与方真实姓名。
                    "name" => $name,
                ],

            );
            $textParams = array();

            try {
                $this->setAlipayConfig($this->alipayConfigStr);
                $exStr = 'alipay_fund_trans_uni_transfer_response';

                Factory::setOptions($this->_getOptions());
                $aliRes = Factory::util()->generic()->execute("alipay.fund.trans.uni.transfer", $textParams, $bizParams);
                write_log('alipay', 'transUniTransfer', ['bizParams'=>$bizParams, 'aliRes'=>$aliRes]);
                //数据处理
                if(!isset($aliRes->httpBody) || empty($aliRes->httpBody)) {
                    write_log('error_alipay', 'transUniTransfer 不存在httpBody', ['bizParams'=>$bizParams, 'aliRes'=>$aliRes]);
                    $result['code'] = -1;
                    $result['msg'] = '支付宝返回数据不存在httpBody';
                    break;
                }
                $aliRes = json_decode($aliRes->httpBody, true);
                if(!isset($aliRes[$exStr]['code'])) {
                    write_log('error_alipay', 'transUniTransfer 不存在code', ['bizParams'=>$bizParams, 'aliRes'=>$aliRes]);
                    $result['code'] = -1;
                    $result['msg'] = '支付宝返回数据格式不存在code';
                    break;
                }
                if(isset($aliRes[$exStr]['sub_code'])) {
                    $result['sub_code'] = $aliRes[$exStr]['sub_code'];
                }
                if($aliRes[$exStr]['code'] != 10000) {
                    $result['msg'] = $aliRes[$exStr]['code'].':'.$aliRes[$exStr]['sub_msg'];
                    break;
                }

                $result['code'] = 1;
                $result['msg'] = '成功';
                $result['data'] = $aliRes[$exStr];
            } catch (\Exception $e) {
                write_log('error_alipay', 'transUniTransfer', ['bizParams'=>$bizParams, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
                $result['code'] = -1;
                $result['msg'] = '系统异常';
                break;
            }
        } while (false);

        return $result;
    }

    /**
     * 转账业务单据查询
     */
    public function transCommonQuery($orderSn)
    {
        $result = [
            'code' => 99,
            'msg' => '失败',
            'data' => [],
        ];
        do {
            $bizParams = array(
                //销售产品码:单笔无密转账到支付宝账户
                "product_code" => 'TRANS_ACCOUNT_NO_PWD',
                //描述特定的业务场景:B2C现金红包、单笔无密转账
                "biz_scene" => 'DIRECT_TRANSFER',
                //商户转账唯一订单号
                "out_biz_no" => $orderSn,
            );
            $textParams = array();

            try {
                $this->setAlipayConfig($this->alipayConfigStr);
                $exStr = 'alipay_fund_trans_common_query_response';

                Factory::setOptions($this->_getOptions());
                $aliRes = Factory::util()->generic()->execute("alipay.fund.trans.common.query", $textParams, $bizParams);
                write_log('alipay', 'transCommonQuery', ['bizParams'=>$bizParams, 'aliRes'=>$aliRes]);
                //数据处理
                if(!isset($aliRes->httpBody) || empty($aliRes->httpBody)) {
                    write_log('error_alipay', 'transCommonQuery 不存在httpBody', ['bizParams'=>$bizParams, 'aliRes'=>$aliRes]);
                    $result['code'] = -1;
                    $result['msg'] = '支付宝返回数据不存在httpBody';
                    break;
                }
                $aliRes = json_decode($aliRes->httpBody, true);
                if(!isset($aliRes[$exStr]['code'])) {
                    write_log('error_alipay', 'transCommonQuery 不存在code', ['bizParams'=>$bizParams, 'aliRes'=>$aliRes]);
                    $result['code'] = -1;
                    $result['msg'] = '支付宝返回数据格式不存在code';
                    break;
                }
                if($aliRes[$exStr]['code'] != 10000) {
                    $result['msg'] = $aliRes[$exStr]['code'].'|'.$aliRes[$exStr]['sub_msg'];
                    break;
                }
                $result = [
                    'code' => 1,
                    'msg' => '成功',
                    'data' => $aliRes[$exStr],
                ];
            } catch (\Exception $e) {
                write_log('error_alipay', 'transCommonQuery', ['bizParams'=>$bizParams, 'message'=>$e->getMessage(), 'line'=>$e->getLine()]);
                $result['code'] = -1;
                $result['msg'] = '系统异常';
                break;
            }
        } while (false);

        return $result;
    }

}